package com.chaoyue.media.utils;

import com.chaoyue.base.model.RestResponse;
import com.chaoyue.base.utils.DateUtils;
import com.chaoyue.base.utils.ObjectUtils;
import com.chaoyue.media.beans.po.MediaFiles;
import io.minio.*;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author whr
 * @version 1.0
 * @description: minio工具类
 * @date 2024/12/14 14:34
 */
@Component
@Slf4j
public class MinioUtils {

    @Autowired
    private MinioClient minioClient;

    public boolean addMediaFilesToMinIO(String localFilePath, String mimeType, String bucket, String objeckName) {
        //上传文件的参数信息
        UploadObjectArgs uploadBucket = null;
        try {
            uploadBucket = UploadObjectArgs.builder().bucket(bucket)
                    .filename(localFilePath)
                    .object(objeckName)
                    .contentType(mimeType)
                    .build();
            //上传文件
            minioClient.uploadObject(uploadBucket);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            //打印错误信息
            log.error("上传文件出错,bucket:{},objeckName:{},错误信息:{}", bucket, objeckName, e.getMessage());
        }
        return false;
    }

    public File downloadFileFromMinIO(String objectName, String bucket) {
        File minioFile = null;
        FileOutputStream outputStream = null;
        try {
            InputStream inputStream = minioClient.getObject(GetObjectArgs.builder().bucket(bucket)
                    .object(objectName)
                    .build());
            minioFile = File.createTempFile("minio", ".merge");
            outputStream = new FileOutputStream(minioFile);
            IOUtils.copy(inputStream, outputStream);
            return minioFile;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    /**
     * @Description: 清理分块文件
     * @Author: whr
     * @Date: 2024/12/14 14:44
     * @Param:
     * @Return:
     */
    public void clearChunkFiles(String chunkFileFolderPath, int chunkTotal) {
        try {
            List<DeleteObject> deleteObjects = Stream.iterate(0, i -> ++i)
                    .limit(chunkTotal)
                    .map(i -> new DeleteObject(chunkFileFolderPath.concat(Integer.toString(i))))
                    .collect(Collectors.toList());

            RemoveObjectsArgs removeObjectsArgs = RemoveObjectsArgs.builder().bucket("video").objects(deleteObjects).build();
            Iterable<Result<DeleteError>> results = minioClient.removeObjects(removeObjectsArgs);
            results.forEach(r -> {
                DeleteError deleteError = null;
                try {
                    deleteError = r.get();
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("清除分块文件失败,objectname:{}", deleteError.objectName(), e);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            log.error("清除分块文件失败,chunkFileFolderPath:{}", chunkFileFolderPath, e);
        }
    }

    public String mergechunks(String fileMd5, int chunkTotal, String bucket, String fileName) {

        //拓展名
        String exeName = fileName.substring(fileName.lastIndexOf("."));
        //合并文件路径
        String objectName = getFilePathByMd5(fileMd5, exeName);

        //分块文件路径
        String chunkFileFolderPath = getChunkFileFolderPath(fileMd5);
        ArrayList<ComposeSource> sources = new ArrayList<>();
        //
        for (int i = 0; i < chunkTotal; i++) {
            ComposeSource composeSource = ComposeSource.builder().bucket(bucket).object(chunkFileFolderPath + i).build();
            sources.add(composeSource);
        }
        ComposeObjectArgs composeObjectArgs = ComposeObjectArgs.builder()
                .bucket(bucket)
                .object(objectName)
                .sources(sources)
                .build();
        try {
            minioClient.composeObject(composeObjectArgs);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("合并文件出错,bucket:{},objectName:{},错误信息:{}" , bucket, objectName, e.getMessage());
            return "";
        }
        return objectName;
    }

    public Boolean checkChunk(String fileMd5, int chunkIndex, String bucket) {
        //分块文件目录
        String chunkFileFolderPath = getChunkFileFolderPath(fileMd5);
        //分块文件路径
        String chunkFilePath = chunkFileFolderPath + chunkIndex;
        ;
        try {
            //获取分块
            GetObjectResponse chunk = minioClient.getObject(GetObjectArgs.builder()
                    .bucket(bucket)
                    .object(chunkFilePath)
                    .build());
            if (ObjectUtils.isNotEmpty(chunk)) {
                return Boolean.TRUE;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Boolean.FALSE;
    }

    public Boolean checkFile(String bucket, String filePath) {
        GetObjectArgs getObjectArgs = GetObjectArgs.builder().bucket(bucket).object(filePath).build();
        try {
            GetObjectResponse file = minioClient.getObject(getObjectArgs);
            if (ObjectUtils.isNotEmpty(file)) {
                //文件已存在
                return Boolean.TRUE;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        //文件不存在
        return Boolean.FALSE;
    }

    /**
     * @Description: 获取分块文件路径
     * @Author: whr
     * @Date: 2024/12/14 14:47
     * @Param:
     * @Return:
     */
    public String getChunkFileFolderPath(String fileMd5) {
        return fileMd5.substring(0, 1) + "/" + fileMd5.substring(1, 2) + "/" + fileMd5 +
                "/" + "chunk" + "/";
    }

    /**
     * @Description: 获取合并后文件的objectName
     * @Author: whr
     * @Date: 2024/12/14 15:17
     * @Param: md5,拓展名
     * @Return:
            */
    public String getFilePathByMd5(String fileMd5, String exeName) {
        return fileMd5.substring(0, 1) + "/" + fileMd5.substring(1, 2) + "/" +
                fileMd5 + "/" + fileMd5 + exeName;
    }

    /**
     * @Description: 获取文件默认存储目录路径 年/月/日
     * @Author: whr
     * @Date: 2024/12/14 15:27
     * @Param:
     * @Return:
            */
    public String getDefaultFolderPath() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
       return   sdf.format(new Date()).replace("-", "/") + "/";

    }


}
